iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Modern Web

擁抱 .Net Core系列 第 24

[Day24] 驗證 - Authencation

  • 分享至 

  • xImage
  •  

驗證(Authencation)跟授權(Authorize)常常讓人搞混(還是只有我)
舉例而言
有一家公司進出大門需要門禁卡
有沒有帶門禁卡與門禁卡是否有效這件事情是驗證(Authencation)
而有些地方,例如董事長辦公室,需要有主管階級的門禁卡才能進出
所以如果小蝦米如我帶著掛著菜逼八的有效門禁卡
依舊無法進出董事長辦公室
帶著有效的資訊,但因為沒有權限而無法做事,稱為授權(Authorize)
而今天主要要談的是
要怎麼拿到門禁卡以及驗證門禁卡是否有效(總不能拿著別家公司的卡來開門吧)的驗證(Authencation)

Issuer, Credential, Revoker

不是很知道怎麼稱呼發門禁卡(token or authencation ticket)的角色,姑且稱呼為Issuer
在訪問他人的大樓的時候,通常要先到櫃台換取門禁卡,櫃台本質上就是Issuer
而在web 應用程式中,要取得token 最常見的方式就是登入(login)

要換門禁卡的時候通常會需要押你的身分證件(Credential)
讓櫃台知道你是誰之後才給你門禁卡

同理,在登入的時候,會需要帶入帳號密碼,這也是一種(Credential)
有了Token 之後,雙方會協商要如何通過門禁,將token放在header/cookie 等等的方式
最後,當你要離開大樓的時候,會再跟門口的警衛或是櫃台跟他說我要離開了
他就會把token 收回
對應web 程式,這件事通常是「登出」 負責撤銷token的為Revoker

身分

Claim

Claim 是當確認使用者身分之後,由issuer發派的
他是描述使用者資訊的物件
可以記錄使用者姓名,電話,email等基本資訊
又或者是使用者的權限(董事長,菜逼八)等等
這個物件最後會作為token的一部分(我的門禁卡上記錄著我是誰,我的權限是菜逼八)

Claim.cs(節錄)

public class Claim
{
    protected virtual byte[]? CustomSerializationData
    {
        get
        {
            return _userSerializationData;
        }
    }

    public string Issuer
    {
        get { return _issuer; }
    }

    public string OriginalIssuer
    {
        get { return _originalIssuer; }
    }

    public IDictionary<string, string> Properties
    {
        get
        {
            if (_properties == null)
            {
                _properties = new Dictionary<string, string>();
            }
            return _properties;
        }
    }

    public ClaimsIdentity? Subject
    {
        get { return _subject; }
    }

    public string Type
    {
        get { return _type; }
    }

    public string Value
    {
        get { return _value; }
    }

    public string ValueType
    {
        get { return _valueType; }
    }
}

上面列的是幾個比較重要的屬性

  • Type表示Claim所記錄的東西 通常會是ClaimTypesmsdn 裡的其中一項,也可以自訂
  • Value則是記錄對應的值
    舉例而言,有一個Claim物件用來記錄我的Email
    Type就會是 ClaimTypes.Email
    Value 就會是 my_mail@gmail.com
  • Issuer跟OriginalIssuer 表示這個Claim是誰提供的,通常這兩個值會是一樣的,但也有可能原始提供者是第三方,但轉到你Server之後把提供者改成你的Server了
  • Properties: 用來儲放額外的資訊
  • ValueType: 因為在傳輸時都是以字串表示Value,ValueType欄位可以用來聲明Value 的型別
  • Subject: 下面提

ClaimIdentity

IIdentity

字面翻譯是身分,裡面有個表現這個身分的稱謂Name
以及這個身分應該要如何驗證的AuthenticationType
還有是否被驗證過的IsAuthenticated

public interface IIdentity
{
    // Access to the name string
    string? Name { get; }

    // Access to Authentication 'type' info
    string? AuthenticationType { get; }

    // Determine if this represents the unauthenticated identity
    bool IsAuthenticated { get; }
}

ClaimIdentity

這是一個很多咚咚的Class
繼承了IIdentity
source code
比較重要的是他有一個instanceClaims 的屬性
這個屬性存放了描述這個身分所有對應的Claim

private readonly List<Claim> _instanceClaims = new List<Claim>();


同樣的Claim上所紀錄的Subject 則會assign給對應的ClaimIdentity

Principal

對驗證系統來說,接受認證的可能是一個實體的人
也有可能是一個application

IPrincipal

對驗證系統來說
都會使用IPrincipal來表示User的概念

public interface IPrincipal
{
    // Retrieve the identity object
    IIdentity? Identity { get; }

    // Perform a check for a specific role
    bool IsInRole(string role);
}

IsInRole()方法可以決定這個身分是不是有權限操作要求的資源

ClaimsPrincipal

ClaimIdentity 中包含了許多的Claim
ClaimsPrincipal 中則包含了很多的 ClaimIdentity source

一個使用者可以有多個身分,每個身分可能有不同的Claim
對於實作的IsInRole方法
只要其中一個身分有Claim為該角色的話就會回傳true

舉例而言
小陳這個使用者(ClaimsPrincipal)擁有董事長、公司職員的(ClaimIdentity)
董事長這個ClaimIdentity中有個Type為ClaimType.RoleValue 為董事長的 Claim
那麼呼叫IsInRole("董事長")就會回傳true

另外,雖然小陳有很多身分
但是在使用IPrincipal呼叫Identity的時候
必須決定一個主要回傳的身分(如果我是小陳,我就會回傳董事長的身分)


上一篇
[Day23] 路由 Routing - 2
下一篇
[Day25] 驗證 - Authentication - 2
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言